package cn.tqfeiyang.smartadmin.business.organization.service;

import cn.tqfeiyang.smartadmin.business.organization.entity.DepartmentEntity;
import cn.tqfeiyang.smartadmin.business.organization.mapper.DepartmentMapper;
import cn.tqfeiyang.smartadmin.business.organization.response.DepartmentQueryVO;
import cn.tqfeiyang.smartadmin.business.organization.response.DepartmentTreeVO;

import cn.tqfeiyang.smartadmin.commons.mybatis.IEntityCache;
import cn.tqfeiyang.smartadmin.commons.toolbox.BeanUtils;
import cn.tqfeiyang.smartadmin.commons.toolbox.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.math.NumberUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import jakarta.annotation.Resource;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 部门tree服务
 *
 * @author tqfeiyang
 * @since 2024-10-18
 */
@Service
@Slf4j
public class DepartmentTreeService implements IEntityCache<DepartmentEntity> {

    /**
     * 部门列表缓存
     */
    private static final String DEPARTMENT_LIST_CACHE = "business:organization:department_list_cache";

    /**
     * 部门map缓存
     */
    private static final String DEPARTMENT_MAP_CACHE = "business:organization:department_map_cache";

    /**
     * 部门路径缓存
     */
    private static final String DEPARTMENT_PATH_CACHE = "business:organization:department_path_cache";

    /**
     * 部门树缓存
     */
    private static final String DEPARTMENT_TREE_CACHE = "business:organization:department_tree_cache";


    /**
     * 某个部门以及下级的id列表
     */
    public static final String DEPARTMENT_SELF_CHILDREN_CACHE = "business:organization:department_self_children_cache";

    /**
     * 部门映射接口
     */
    @Resource
    private DepartmentMapper departmentMapper;

    /**
     * 清空部门缓存
     */
    @CacheEvict(value = {
            DEPARTMENT_LIST_CACHE,
            DEPARTMENT_MAP_CACHE,
            DEPARTMENT_PATH_CACHE,
            DEPARTMENT_TREE_CACHE}, allEntries = true)
    @Override
    public void clearCache() {
        log.info("清空部门缓存");
    }

    /**
     * 查询部门列表
     *
     * @return 部门列表
     */
    @Cacheable(DEPARTMENT_LIST_CACHE)
    public List<DepartmentQueryVO> getDepartmentList() {
        return departmentMapper.queryDepartments(null);
    }

    /**
     * 查询部门map
     *
     * @return 部门map
     */
    @Cacheable(DEPARTMENT_MAP_CACHE)
    public Map<Long, DepartmentQueryVO> getDepartmentMap() {
        return getDepartmentList().stream()
                .collect(Collectors.toMap(DepartmentQueryVO::getDepartmentId, Function.identity()));
    }

    /**
     * 查询部门树
     *
     * @return 部门树
     */
    @Cacheable(DEPARTMENT_TREE_CACHE)
    public List<DepartmentTreeVO> getDepartmentTree() {
        List<DepartmentQueryVO> list = getDepartmentList();
        return this.buildTree(list);
    }

    /**
     * 缓存某个部门的下级id列表
     */
    @Cacheable(DEPARTMENT_SELF_CHILDREN_CACHE)
    public List<Long> getDepartmentSelfAndChildren(Long departmentId) {
        List<DepartmentQueryVO> voList = getDepartmentList();
        return this.selfAndChildrenIdList(departmentId, voList);
    }

    /**
     * 查询部门的路径名称
     *
     * @return 部门路径map
     */
    @Cacheable(DEPARTMENT_PATH_CACHE)
    public Map<Long, String> getDepartmentPathMap() {
        List<DepartmentQueryVO> voList = getDepartmentList();
        Map<Long, DepartmentQueryVO> voMap = voList.stream().collect(Collectors.toMap(DepartmentQueryVO::getDepartmentId, Function.identity()));

        Map<Long, String> pathNameMap = new HashMap<>();
        for (DepartmentQueryVO vo : voList) {
            String pathName = this.buildPath(vo, voMap);
            pathNameMap.put(vo.getDepartmentId(), pathName);
        }

        return pathNameMap;
    }

    private String buildPath(DepartmentQueryVO vo, Map<Long, DepartmentQueryVO> voMap) {
        if (Objects.equals(vo.getParentId(), NumberUtils.LONG_ZERO)) {
            return vo.getName();
        }
        //父节点
        DepartmentQueryVO parentVo = voMap.get(vo.getParentId());
        if (parentVo == null) {
            return vo.getName();
        }
        String pathName = buildPath(parentVo, voMap);
        return pathName + "/" + vo.getName();
    }


    // ---------------------- 构造树的一些方法 ------------------------------

    /**
     * 构建树结构
     */
    private List<DepartmentTreeVO> buildTree(List<DepartmentQueryVO> voList) {
        if (CollectionUtils.isEmpty(voList)) {
            return new ArrayList<>();
        }
        List<DepartmentQueryVO> rootList = voList.stream().filter(e -> e.getParentId() == null || Objects.equals(e.getParentId(), NumberUtils.LONG_ZERO)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(rootList)) {
            return new ArrayList<>();
        }
        List<DepartmentTreeVO> treeVOList = BeanUtils.copyList(rootList, DepartmentTreeVO.class);
        this.recursiveBuildTree(treeVOList, voList);
        return treeVOList;
    }

    /**
     * 构建所有根节点的下级树形结构
     */
    private void recursiveBuildTree(List<DepartmentTreeVO> nodeList, List<DepartmentQueryVO> allList) {
        int nodeSize = nodeList.size();
        for (int i = 0; i < nodeSize; i++) {
            int preIndex = i - 1;
            int nextIndex = i + 1;
            DepartmentTreeVO node = nodeList.get(i);
            if (preIndex > -1) {
                node.setPreId(nodeList.get(preIndex).getDepartmentId());
            }
            if (nextIndex < nodeSize) {
                node.setNextId(nodeList.get(nextIndex).getDepartmentId());
            }

            List<Long> selfAndAllChildrenIdList = selfAndChildrenIdList(node.getDepartmentId(), allList);
            node.setSelfAndAllChildrenIdList(selfAndAllChildrenIdList);

            List<DepartmentTreeVO> children = getChildren(node.getDepartmentId(), allList);
            if (CollectionUtils.isNotEmpty(children)) {
                node.setChildren(children);
                this.recursiveBuildTree(children, allList);
            }
        }
    }

    /**
     * 获取子元素
     */
    private List<DepartmentTreeVO> getChildren(Long departmentId, List<DepartmentQueryVO> voList) {
        List<DepartmentQueryVO> childrenEntityList = voList.stream().filter(e -> departmentId.equals(e.getParentId())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(childrenEntityList)) {
            return new ArrayList<>();
        }
        return BeanUtils.copyList(childrenEntityList, DepartmentTreeVO.class);
    }

    /**
     * 获取当前以及下属id
     */
    private List<Long> selfAndChildrenIdList(Long departmentId, List<DepartmentQueryVO> voList) {
        List<Long> selfAndChildrenIdList = new ArrayList<>();
        if (CollectionUtils.isEmpty(voList)) {
            return selfAndChildrenIdList;
        }
        selfAndChildrenIdList.add(departmentId);
        List<DepartmentTreeVO> children = this.getChildren(departmentId, voList);
        if (CollectionUtils.isEmpty(children)) {
            return selfAndChildrenIdList;
        }
        List<Long> childrenIdList = children.stream().map(DepartmentTreeVO::getDepartmentId).collect(Collectors.toList());
        selfAndChildrenIdList.addAll(childrenIdList);
        for (Long childId : childrenIdList) {
            this.selfAndChildrenRecursion(selfAndChildrenIdList, childId, voList);
        }
        return selfAndChildrenIdList;
    }

    /**
     * 递归查询
     */
    private void selfAndChildrenRecursion(List<Long> selfAndChildrenIdList, Long departmentId, List<DepartmentQueryVO> voList) {
        List<DepartmentTreeVO> children = this.getChildren(departmentId, voList);
        if (CollectionUtils.isEmpty(children)) {
            return;
        }
        List<Long> childrenIdList = children.stream().map(DepartmentTreeVO::getDepartmentId).collect(Collectors.toList());
        selfAndChildrenIdList.addAll(childrenIdList);
        for (Long childId : childrenIdList) {
            this.selfAndChildrenRecursion(selfAndChildrenIdList, childId, voList);
        }
    }
}
